#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Common.Extensions/DictionaryExtensions 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       字典扩展方法，提供对Dictionary类型的各种扩展操作
* 类 名：       DictionaryExtensions
* 创建时间：  2025/5/21 18:45:28
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Collections.Generic
{
    /// <summary>
    ///  Dictionary扩展
    /// </summary>
    public static class DictionaryExtensions
    {
        /// <summary>
        /// 尝试从字典中获取指定键的值并进行类型转换
        /// </summary>
        /// <typeparam name="T">要获取的值的类型</typeparam>
        /// <param name="dictionary">源字典，键为string，值为object</param>
        /// <param name="key">要查找的键名</param>
        /// <param name="value">输出参数，如果找到且类型匹配则返回转换后的值，否则返回default(T)</param>
        /// <returns>
        /// 如果键存在且值可以转换为类型T返回true，否则返回false
        /// </returns>
        internal static bool TryGetValue<T>(this IDictionary<string, object> dictionary, string key, out T value)
        {
            object valueObj;
            if (dictionary.TryGetValue(key, out valueObj) && valueObj is T)
            {
                value = (T)valueObj;
                return true;
            }

            value = default;
            return false;
        }
    /// <summary>
        /// 向字典中添加键值对，如果键已存在则不添加
        /// </summary>
        /// <typeparam name="TKey">键类型</typeparam>
        /// <typeparam name="TValue">值类型</typeparam>
        /// <param name="dictionary">字典对象</param>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns>如果添加成功返回true，否则返回false</returns>
        public static bool TryAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
        {
            if (dictionary.ContainsKey(key))
                return false;

            dictionary.Add(key, value);
            return true;
        }

        /// <summary>
        /// 获取字典中指定键的值，如果键不存在则返回默认值
        /// </summary>
        /// <typeparam name="TKey">键类型</typeparam>
        /// <typeparam name="TValue">值类型</typeparam>
        /// <param name="dictionary">字典对象</param>
        /// <param name="key">键</param>
        /// <returns>键对应的值或默认值</returns>
        public static TValue GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
        {
            return dictionary.TryGetValue(key, out var value) ? value : default;
        }

        /// <summary>
        /// 将目标字典合并到源字典中
        /// </summary>
        /// <typeparam name="TKey">键类型</typeparam>
        /// <typeparam name="TValue">值类型</typeparam>
        /// <param name="source">要合并到的目标字典(将被修改)</param>
        /// <param name="target">要合并的源字典</param>
        /// <param name="replaceExisting">
        /// 是否替换已存在的键值对：
        /// true - 替换已存在的键值对
        /// false - 保留源字典中的值
        /// </param>
        /// <remarks>
        /// 该方法会遍历目标字典的所有键值对：
        /// 1. 如果键不存在于源字典，则添加该键值对
        /// 2. 如果键已存在且replaceExisting为true，则替换该键的值
        /// </remarks>
        public static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> source, 
            IDictionary<TKey, TValue> target, 
            bool replaceExisting = true)
        {
            foreach (var pair in target)
            {
                if (!source.ContainsKey(pair.Key) || replaceExisting)
                {
                    source[pair.Key] = pair.Value;
                }
            }
        }

        /// <summary>
        /// Gets a value from the dictionary with given key. Returns default value if can not find.
        /// </summary>
        /// <param name="dictionary">Dictionary to check and get</param>
        /// <param name="key">Key to find the value</param>
        /// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
        /// <typeparam name="TKey">Type of the key</typeparam>
        /// <typeparam name="TValue">Type of the value</typeparam>
        /// <returns>Value if found, default if can not found.</returns>
        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> factory)
        {
            return dictionary.GetOrAdd(key, k => factory());
        }

        /// <summary>
        /// Gets a value from the concurrent dictionary with given key. Returns default value if can not find.
        /// </summary>
        /// <param name="dictionary">Concurrent dictionary to check and get</param>
        /// <param name="key">Key to find the value</param>
        /// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
        /// <typeparam name="TKey">Type of the key</typeparam>
        /// <typeparam name="TValue">Type of the value</typeparam>
        /// <returns>Value if found, default if can not found.</returns>
        public static TValue GetOrAdd<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dictionary, TKey key, Func<TValue> factory)
        {
            return dictionary.GetOrAdd(key, k => factory());
        }
        /// <summary>
        /// Gets a value from the dictionary with given key. Returns default value if can not find.
        /// </summary>
        /// <param name="dictionary">Dictionary to check and get</param>
        /// <param name="key">Key to find the value</param>
        /// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
        /// <typeparam name="TKey">Type of the key</typeparam>
        /// <typeparam name="TValue">Type of the value</typeparam>
        /// <returns>Value if found, default if can not found.</returns>
        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> factory)
        {
            TValue obj;
            if (dictionary.TryGetValue(key, out obj))
            {
                return obj;
            }

            return dictionary[key] = factory(key);
        }
    }
}
